﻿
using EasyAdmin.Domain.Entities.Systems;
using IdentityModel.Client;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Routing.Template;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;

namespace EasyAdmin.Web.ApiCollectors
{
    public class ApiCollector : IApiCollector
    {
        private readonly ApiCollectorOptions _options;
        private readonly IApiDescriptionGroupCollectionProvider _apiDescProvider;
        public ApiCollector(IApiDescriptionGroupCollectionProvider apiDescProvider, ApiCollectorOptions options)
        {
            this._apiDescProvider = apiDescProvider;
            this._options = options;
        }
        /// <summary>
        /// 收集所有API信息
        /// </summary>
        /// <returns></returns>
        public async Task<IEnumerable<SysApiEndpoint>> CollectApisAsync()
        {
            XDocument xmlDoc = null;
            if (_options != null && !string.IsNullOrWhiteSpace(_options.xmlFilePath) && File.Exists(_options.xmlFilePath))
            {
                xmlDoc = XDocument.Load(_options.xmlFilePath);
            }
            var groups = _apiDescProvider.ApiDescriptionGroups.Items;
            var endpoints = new List<SysApiEndpoint>();
            foreach (var group in groups)
            {
                foreach (var desc in group.Items)
                {
                    SysApiEndpoint apiEndpoint = new SysApiEndpoint();
                    var actionDescriptor = desc.ActionDescriptor as ControllerActionDescriptor;
                    var descAttr = actionDescriptor.MethodInfo.GetCustomAttributes(typeof(DescriptionAttribute), true).OfType<DescriptionAttribute>().FirstOrDefault();
                    if (descAttr != null) {
                        apiEndpoint.ActionSummary = descAttr.Description;
                    }
                    if (string.IsNullOrWhiteSpace(apiEndpoint.ActionSummary) && actionDescriptor != null) {
                        var xmlComments = GetXmlCommentsForMethod(xmlDoc, actionDescriptor.MethodInfo);
                        apiEndpoint.ActionSummary = xmlComments;
                    }      
                    apiEndpoint.HttpMethod = desc.HttpMethod ?? "ANY";                   
                    apiEndpoint.RouteTemplate = desc.RelativePath!;                 
                    apiEndpoint.ControllerName = desc.ActionDescriptor.RouteValues["controller"]!;
                    apiEndpoint.ActionName = desc.ActionDescriptor.RouteValues["action"]!;
                    apiEndpoint.Parameters = JsonSerializer.Serialize(desc.ParameterDescriptions.Select(p => new
                    {
                        p.Name,
                        Type = p.Type?.Name,
                        p.IsRequired
                    }));
                    endpoints.Add(apiEndpoint);
                }
            }
            return endpoints;
        }

        private string GetXmlCommentsForMethod(XDocument xmlDoc, MethodInfo methodInfo)
        {
            if (xmlDoc == null) return string.Empty;
            var memberName = $"M:{methodInfo.DeclaringType.FullName}.{methodInfo.Name}";
            var parameters = methodInfo.GetParameters();
            if (parameters.Any())
                memberName += $"({string.Join(",", parameters.Select(p => p.ParameterType.FullName))})";
            var memberElement = xmlDoc.Descendants("member")
                .FirstOrDefault(m => m.Attribute("name")?.Value == memberName);
            return memberElement?.Element("summary")?.Value.Trim() ?? string.Empty;
        }
    }
}
